﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Refl
{
    //TODO: Implements: synonym functionality
    //synonym Bool3 = Triple;
    using Bool3 = Triple;
    //----------------------------------------
    //Triple class is using a bool? as a workaround for C# implementation.
    //Reflective-C# native implementation should not use workarounds. consider defining it in C++.
    public class Triple
    {
        /// <summary>
        /// Equivalent to the boolean 'true'
        /// </summary>
        public static Triple True = new Triple(true);
        public static readonly string TrueString = "true";
        /// <summary>
        /// Equivalent to the boolean 'false'
        /// </summary>
        public static Triple False = new Triple(false);
        public static readonly string FalseString = "false";
        /// <summary>
        /// Third value of the Triple class. This is neither true nor false.
        /// </summary>
        public static Triple None = new Triple(null);
        public static readonly string NoneString = "none";
        /// <summary>
        /// Same as Triple.None.
        /// </summary>
        public static Triple Unknown = new Triple(null);
        public static readonly string UnknownString = "none";

        protected bool? _value;

        public Triple(bool? value)
        {
            _value = value;
        }
        public Triple()
        {
            _value = null;
        }
        public override bool Equals(object obj)
        {
            if (obj.GetType() == typeof(bool))
            {
                return (_value==(bool)obj);
            }
            if (obj.GetType() == typeof(bool?))
            {
                return (_value == (bool?)obj);
            }
            if (obj.GetType() == typeof(Triple))
            {
                return (_value == (bool?)obj);
            }
            return false;
        }
        public override int GetHashCode()
        {
            switch (_value)
            {
                case false:
                    return -1;
                case null:
                    return 0;
                case true:
                    return 1;
                default:
                    return 0;
            }
        }
        public static implicit operator Triple(bool arg)
        {
            return new Triple((bool?)arg);
        }
        public static implicit operator Triple(bool? arg)
        {
            return new Triple(arg);
        }
        public static bool operator ==(Triple t, bool b)
        {
            return (t._value == (bool?)b);
        }
        public static bool operator !=(Triple t, bool b)
        {
            return (t._value != (bool?)b);
        }
        public static bool operator ==(bool b, Triple t)
        {
            return (t._value == (bool?)b);
        }
        public static bool operator !=(bool b, Triple t)
        {
            return (t._value != (bool?)b);
        }
        public static bool operator ==(Triple t1, Triple t2)
        {
            return (t1._value == t2._value);
        }
        public static bool operator !=(Triple t1, Triple t2)
        {
            return (t1._value != t2._value);
        }
        public static implicit operator bool?(Triple t)
        {
            return t._value;
        }
        public static implicit operator bool(Triple t)
        {
            if (t._value == null)
            {
                throw new InvalidOperationException("Cannot cast Triple.None to bool.");
            }
            return (bool)t._value;
        }
        public override string ToString()
        {
            if (_value == false)
            {
                return "false";
            }
            else if (_value == true)
            {
                return "true";
            }
            else
            {
                return "none";
            }
        }
    }
}
